The main idea is to globally allocate only those registers with global significance.
We permanently dedicate the CONT register to point to the current control stack environment. This is the "frame pointer" in standard terminology. It isn't possible to get pack to allocate this register on an as-needed basis due to the classic phase-ordering problem. We need to know if TNs are allocated on the stack before we can determine tell how badly we need a frame pointer register. This is of little significance with the control stack environment, since we almost always need one, and if there are any stack TNs, we must allocate the frame pointer in a register, since there is nowhere else to put it. The problem is more severe with a number stack environment pointer. We can't dedicate a register to it, since we usually don't have any TNs on the number stack. The only easy solution is to always allocate the number stack environment pointer on the control stack. This really isn't too bad, when you compare the cost of doing an extra memory reference to get at the number stack to the cost of number-consing.
We also dedicate the ENV register to the current constant pool. It would be possible to explicitly allocate the constant pointer as needed if we explicitly represented non-immediate constant access by a VOP, but this would be extra work, and there are major advantages to representing all constants using TNs. Another potential efficiency advantage is since the same constant pool is shared by all the code in a component, we need only initialize ENV on entry to the component. When we make local calls, we don't have to do anything to make the constants available to the callee.
Since the constant pool will also contain the code vector and the debug info, having it in a known place may make life easier for GC and the debugger. We may not be able to count on it too much, though, since ENV holds other things will calls are in progress, and might be pretty random if we jumped into hyperspace.
Runtime environment:
CONT: the current control stack context. PC is assumed to be accessible to the debugger when an error happens. Current-Catch: pointer to the current catch frame. Format of frame is assumed. Current-Unwind-Protect: current unwind protect frame. Similar to catch.
If shallow-bind, binding stack and binding stack pointer. If deep-bind, current special binding. Format of binding frame assumed.
Everything depends on the current environment, which is CONT.
PC OLD-CONT ENV A<n> CONT CS